home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / WIN_PRO / DS-1.ZIP;1 / RTT.ZIP / RTTLEX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-10  |  15.1 KB  |  368 lines

  1. /*
  2.  * This lexical analyser uses the preprocessor to convert text into tokens.
  3.  *  The lexical anayser discards white space, checks to see if identifiers
  4.  *  are reserved words or typedef names, makes sure single characters
  5.  *  are valid tokens, and converts preprocessor constants into the
  6.  *  various C constants.
  7.  */
  8. #include <ctype.h>
  9. #include "rtt.h"
  10.  
  11. /*
  12.  * Prototype for static function.
  13.  */
  14. hidden int int_suffix Params((char *s));
  15.  
  16. int lex_state = DfltLex;
  17.  
  18. char *ident = "ident";
  19.  
  20. /*
  21.  * Characters are used as token id's for single character tokens. The
  22.  *  following table indicates which ones can be valid for RTL.
  23.  *
  24.  * Warning - ascii dependence, must be changed for ebcdic.
  25.  *
  26.  */
  27. #define GoodChar(c) ((c) < 127 && good_char[c])
  28. static int good_char[128] = {
  29.    0  /* \000 */,   0  /* \001 */,   0  /* \002 */,   0  /* \003 */,
  30.    0  /* \004 */,   0  /* \005 */,   0  /* \006 */,   0  /* \007 */,
  31.    0  /*  \b  */,   0  /*  \t  */,   0  /*  \n  */,   0  /*  \v  */,
  32.    0  /*  \f  */,   0  /*  \r  */,   0  /* \016 */,   0  /* \017 */,
  33.    0  /* \020 */,   0  /* \021 */,   0  /* \022 */,   0  /* \023 */,
  34.    0  /* \024 */,   0  /* \025 */,   0  /* \026 */,   0  /* \027 */,
  35.    0  /* \030 */,   0  /* \031 */,   0  /* \032 */,   0  /*  \e  */,
  36.    0  /* \034 */,   0  /* \035 */,   0  /* \036 */,   0  /* \037 */,
  37.    0  /*      */,   1  /*  !   */,   0  /*  \   */,   0  /*  #   */,
  38.    0  /*  $   */,   1  /*  %   */,   1  /*  &   */,   0  /*  '   */,
  39.    1  /*  (   */,   1  /*  )   */,   1  /*  *   */,   1  /*  +   */,
  40.    1  /*  ,   */,   1  /*  -   */,   1  /*  .   */,   1  /*  /   */,
  41.    0  /*  0   */,   0  /*  1   */,   0  /*  2   */,   0  /*  3   */,
  42.    0  /*  4   */,   0  /*  5   */,   0  /*  6   */,   0  /*  7   */,
  43.    0  /*  8   */,   0  /*  9   */,   1  /*  :   */,   1  /*  ;   */,
  44.    1  /*  <   */,   1  /*  =   */,   1  /*  >   */,   1  /*  ?   */,
  45.    0  /*  @   */,   0  /*  A   */,   0  /*  B   */,   0  /*  C   */,
  46.    0  /*  D   */,   0  /*  E   */,   0  /*  F   */,   0  /*  G   */,
  47.    0  /*  H   */,   0  /*  I   */,   0  /*  J   */,   0  /*  K   */,
  48.    0  /*  L   */,   0  /*  M   */,   0  /*  N   */,   0  /*  O   */,
  49.    0  /*  P   */,   0  /*  Q   */,   0  /*  R   */,   0  /*  S   */,
  50.    0  /*  T   */,   0  /*  U   */,   0  /*  V   */,   0  /*  W   */,
  51.    0  /*  X   */,   0  /*  Y   */,   0  /*  Z   */,   1  /*  [   */,
  52.    1  /*  \\  */,   1  /*  ]   */,   1  /*  ^   */,   0  /*  _   */,
  53.    0  /*  `   */,   0  /*  a   */,   0  /*  b   */,   0  /*  c   */,
  54.    0  /*  d   */,   0  /*  e   */,   0  /*  f   */,   0  /*  g   */,
  55.    0  /*  h   */,   0  /*  i   */,   0  /*  j   */,   0  /*  k   */,
  56.    0  /*  l   */,   0  /*  m   */,   0  /*  n   */,   0  /*  o   */,
  57.    0  /*  p   */,   0  /*  q   */,   0  /*  r   */,   0  /*  s   */,
  58.    0  /*  t   */,   0  /*  u   */,   0  /*  v   */,   0  /*  w   */,
  59.    0  /*  x   */,   0  /*  y   */,   0  /*  z   */,   1  /*  {   */,
  60.    1  /*  |   */,   1  /*  }   */,   1  /*  ~   */,   0  /*  \d  */
  61.    };
  62.  
  63. /*
  64.  * init_lex - initialize lexical analyzer.
  65.  */
  66. novalue init_lex()
  67.    {
  68.    static int first_time = 1;
  69.  
  70.    if (first_time) {
  71.       first_time = 0;
  72.       ident = spec_str(ident);  /* install ident in string table */
  73.       /*
  74.        * install C keywords into the symbol table
  75.        */
  76.       sym_add(Auto,          spec_str("auto"),          OtherDcl, 0);
  77.       sym_add(Break,         spec_str("break"),         OtherDcl, 0);
  78.       sym_add(Case,          spec_str("case"),          OtherDcl, 0);
  79.       sym_add(Char,          spec_str("char"),          OtherDcl, 0);
  80.       sym_add(Const,         spec_str("const"),         OtherDcl, 0);
  81.       sym_add(Continue,      spec_str("continue"),      OtherDcl, 0);
  82.       sym_add(Default,       spec_str("default"),       OtherDcl, 0);
  83.       sym_add(Do,            spec_str("do"),            OtherDcl, 0);
  84.       sym_add(Doubl,         spec_str("double"),        OtherDcl, 0);
  85.       sym_add(Else,          spec_str("else"),          OtherDcl, 0);
  86.       sym_add(Enum,          spec_str("enum"),          OtherDcl, 0);
  87.       sym_add(Extern,        spec_str("extern"),        OtherDcl, 0);
  88.       sym_add(Float,         spec_str("float"),         OtherDcl, 0);
  89.       sym_add(For,           spec_str("for"),           OtherDcl, 0);
  90.       sym_add(Goto,          spec_str("goto"),          OtherDcl, 0);
  91.       sym_add(If,            spec_str("if"),            OtherDcl, 0);
  92.       sym_add(Int,           spec_str("int"),           OtherDcl, 0);
  93.       sym_add(Long,          spec_str("long"),          OtherDcl, 0);
  94.       sym_add(Register,      spec_str("register"),      OtherDcl, 0);
  95.       sym_add(Return,        spec_str("return"),        OtherDcl, 0);
  96.       sym_add(Short,         spec_str("short"),         OtherDcl, 0);
  97.       sym_add(Signed,        spec_str("signed"),        OtherDcl, 0);
  98.       sym_add(Sizeof,        spec_str("sizeof"),        OtherDcl, 0);
  99.       sym_add(Static,        spec_str("static"),        OtherDcl, 0);
  100.       sym_add(Struct,        spec_str("struct"),        OtherDcl, 0);
  101.       sym_add(Switch,        spec_str("switch"),        OtherDcl, 0);
  102.       sym_add(Typedef,       spec_str("typedef"),       OtherDcl, 0);
  103.       sym_add(Union,         spec_str("union"),         OtherDcl, 0);
  104.       sym_add(Unsigned,      spec_str("unsigned"),      OtherDcl, 0);
  105.       sym_add(Void,          spec_str("void"),          OtherDcl, 0);
  106.       sym_add(Volatile,      spec_str("volatile"),      OtherDcl, 0);
  107.       sym_add(While,         spec_str("while"),         OtherDcl, 0);
  108.  
  109.       /*
  110.        * Install keywords from run-time interface language.
  111.        */
  112.       sym_add(Abstract,      spec_str("abstract"),      OtherDcl, 0);
  113.       sym_add(All_fields,    spec_str("all_fields"),    OtherDcl, 0);
  114.       sym_add(Body,          spec_str("body"),          OtherDcl, 0);
  115.       sym_add(C_Double,      spec_str("C_double"),      OtherDcl, 0);
  116.       sym_add(C_Integer,     spec_str("C_integer"),     OtherDcl, 0);
  117.       sym_add(C_String,      spec_str("C_string"),      OtherDcl, 0);
  118.       sym_add(Cnv,           spec_str("cnv"),           OtherDcl, 0);
  119.       sym_add(Co_expression, spec_str("co_expression"), OtherDcl, 0);
  120.       sym_add(Constant,      spec_str("constant"),      OtherDcl, 0);
  121.       sym_add(Cset,          spec_str("cset"),          OtherDcl, 0);
  122.       sym_add(Declare,       spec_str("declare"),       OtherDcl, 0);
  123.       sym_add(Def,           spec_str("def"),           OtherDcl, 0);
  124.       sym_add(Empty_type,    spec_str("empty_type"),    OtherDcl, 0);
  125.       sym_add(End,           spec_str("end"),           OtherDcl, 0);
  126.       sym_add(Errorfail,     spec_str("errorfail"),     OtherDcl, 0);
  127.       sym_add(Exact,         spec_str("exact"),         OtherDcl, 0);
  128.       sym_add(Fail,          spec_str("fail"),          OtherDcl, 0);
  129.       sym_add(File,          spec_str("file"),          OtherDcl, 0);
  130.       sym_add(Function,      spec_str("function"),      OtherDcl, 0);
  131.       sym_add(Inline,        spec_str("inline"),        OtherDcl, 0);
  132.       sym_add(Integer,       spec_str("integer"),       OtherDcl, 0);
  133.       sym_add(Is,            spec_str("is"),            OtherDcl, 0);
  134.       sym_add(Key,           spec_str("key"),           OtherDcl, 0);
  135.       sym_add(Keyword,       spec_str("keyword"),       OtherDcl, 0);
  136.       sym_add(Len_case,      spec_str("len_case"),      OtherDcl, 0);
  137.       sym_add(List,          spec_str("list"),          OtherDcl, 0);
  138.       sym_add(Lst_elem,      spec_str("lst_elem"),      OtherDcl, 0);
  139.       sym_add(Named_var,     spec_str("named_var"),     OtherDcl, 0);
  140.       sym_add(New,           spec_str("new"),           OtherDcl, 0);
  141.       sym_add(Null,          spec_str("null"),          OtherDcl, 0);
  142.       sym_add(Of,            spec_str("of"),            OtherDcl, 0);
  143.       sym_add(Operator,      spec_str("operator"),      OtherDcl, 0);
  144.       sym_add(Procedure,     spec_str("procedure"),     OtherDcl, 0);
  145.       sym_add(Real,          spec_str("real"),          OtherDcl, 0);
  146.       sym_add(Record,        spec_str("record"),        OtherDcl, 0);
  147.       str_rslt = spec_str("result");
  148.       sym_add(Runerr,        spec_str("runerr"),        OtherDcl, 0);
  149.       sym_add(Set,           spec_str("set"),           OtherDcl, 0);
  150.       sym_add(Set_elem,      spec_str("set_elem"),      OtherDcl, 0);
  151.       sym_add(Store,         spec_str("store"),         OtherDcl, 0);
  152.       sym_add(Str_var,       spec_str("str_var"),       OtherDcl, 0);
  153.       sym_add(String,        spec_str("string"),        OtherDcl, 0);
  154.       sym_add(Struct_var,    spec_str("struct_var"),    OtherDcl, 0);
  155.       sym_add(Substr,        spec_str("substr"),        OtherDcl, 0);
  156.       sym_add(Suspend,       spec_str("suspend"),       OtherDcl, 0);
  157.       sym_add(Table,         spec_str("table"),         OtherDcl, 0);
  158.       sym_add(Tended,        spec_str("tended"),        OtherDcl, 0);
  159.       sym_add(Tbl_elem,      spec_str("tbl_elem"),      OtherDcl, 0);
  160.       sym_add(Then,          spec_str("then"),          OtherDcl, 0);
  161.       sym_add(Tmp_cset,      spec_str("tmp_cset"),      OtherDcl, 0);
  162.       sym_add(Tmp_string,    spec_str("tmp_string"),    OtherDcl, 0);
  163.       sym_add(Trpd_tbl,      spec_str("trpd_tbl"),      OtherDcl, 0);
  164.       sym_add(Type,          spec_str("type"),          OtherDcl, 0);
  165.       sym_add(Type_case,     spec_str("type_case"),     OtherDcl, 0);
  166.       sym_add(Kywdint,       spec_str("kywdint"),       OtherDcl, 0);
  167.       sym_add(Kywdpos,       spec_str("kywdpos"),       OtherDcl, 0);
  168.       sym_add(Kywdsubj,      spec_str("kywdsubj"),      OtherDcl, 0);
  169.       sym_add(Tvsubs,        spec_str("tvsubs"),        OtherDcl, 0);
  170.       sym_add(Tvtbl,         spec_str("tvtbl"),         OtherDcl, 0);
  171.       sym_add(Underef,       spec_str("underef"),       OtherDcl, 0);
  172.       sym_add(Variable,      spec_str("variable"),      OtherDcl, 0);
  173.       }
  174.    }
  175.  
  176. /*
  177.  * int_suffix - we have reached the end of what seems to be an integer
  178.  *  constant. check for a valid suffix.
  179.  */
  180. static int int_suffix(s)
  181. char *s;
  182.    {
  183.    int tok_id;
  184.  
  185.    if (*s == 'u' || *s == 'U') {
  186.       ++s;
  187.       if (*s == 'l' || *s == 'L') {
  188.          ++s;
  189.          tok_id = ULIntConst;  /* unsigned long */
  190.          }
  191.       else
  192.          tok_id  = UIntConst;  /* unsigned */
  193.       }
  194.    else if (*s == 'l' || *s == 'L') {
  195.       ++s;
  196.       if (*s == 'u' || *s == 'U') {
  197.          ++s;
  198.          tok_id = ULIntConst;  /* unsigned long */
  199.          }
  200.       else
  201.          tok_id = LIntConst;   /* long */
  202.       }
  203.    else
  204.       tok_id = IntConst;       /* plain int */
  205.    if (*s != '\0')
  206.       errt2(yylval.t, "invalid integer constant: ", yylval.t->image);
  207.    return tok_id;
  208.    }
  209.  
  210. /*
  211.  * yylex - lexical analyzer, called by yacc-generated parser.
  212.  */
  213. int yylex()
  214.    {
  215.    register char *s;
  216.    struct sym_entry *sym;
  217.    struct token *lk_ahead = NULL;
  218.    int is_float;
  219.    struct str_buf *sbuf;
  220.  
  221.    /*
  222.     * See if the last call to yylex() left a token from looking ahead.
  223.     */
  224.    if (lk_ahead == NULL)
  225.       yylval.t = preproc();
  226.    else {
  227.       yylval.t = lk_ahead;
  228.       lk_ahead = NULL;
  229.       }
  230.  
  231.    /*
  232.     * Skip white space, then check for end-of-input.
  233.     */
  234.    while (yylval.t != NULL && yylval.t->tok_id == WhiteSpace) {
  235.       free_t(yylval.t);
  236.       yylval.t = preproc();
  237.       }
  238.    if (yylval.t == NULL)
  239.       return 0;
  240.  
  241.    /*
  242.     * The rtt recognizes ** as an operator in abstract type computations.
  243.     *  The parsing context is indicated by lex_state.
  244.     */
  245.    if (lex_state == TypeComp && yylval.t->tok_id == '*') {
  246.       lk_ahead = preproc();
  247.       if (lk_ahead != NULL && lk_ahead->tok_id == '*') {
  248.          free_t(lk_ahead);
  249.          lk_ahead = NULL;
  250.          yylval.t->tok_id = Intersect;
  251.          yylval.t->image = spec_str("**");
  252.          }
  253.       }
  254.  
  255.    /*
  256.     * Some tokens are passed along without change, but some need special
  257.     *  processing: identifiers, numbers, PpKeep tokens, and single
  258.     *  character tokens.
  259.     */
  260.    if (yylval.t->tok_id == Identifier) {
  261.       /*
  262.        * See if this is an identifier, a reserved word, or typedef name.
  263.        */
  264.       sym = sym_lkup(yylval.t->image);
  265.       if (sym != NULL)
  266.          yylval.t->tok_id = sym->tok_id;
  267.       }
  268.    else if (yylval.t->tok_id == PpNumber) {
  269.       /*
  270.        * Determine what kind of numeric constant this is.
  271.        */
  272.       s = yylval.t->image;
  273.       if (*s == '0' && (*++s == 'x' || *s == 'X')) {
  274.          /*
  275.           * Hex integer constant.
  276.           */
  277.          ++s;
  278.          while (isxdigit(*s))
  279.             ++s;
  280.          yylval.t->tok_id = int_suffix(s);
  281.          }
  282.       else {
  283.          is_float = 0;
  284.          while (isdigit(*s))
  285.              ++s;
  286.          if (*s == '.') {
  287.             is_float = 1;
  288.             ++s;
  289.             while (isdigit(*s))
  290.                ++s;
  291.             }
  292.          if (*s == 'e' || *s == 'E') {
  293.             is_float = 1;
  294.             ++s;
  295.             if (*s == '+' || *s == '-')
  296.                ++s;
  297.             while (isdigit(*s))
  298.                ++s;
  299.             }
  300.          if (is_float) {
  301.             switch (*s) {
  302.                case '\0':
  303.                   yylval.t->tok_id = DblConst;   /* double */
  304.                   break;
  305.                case 'f': case 'F':
  306.                    yylval.t->tok_id = FltConst;  /* float */
  307.                    break;
  308.                case 'l': case 'L':
  309.                    yylval.t->tok_id = LDblConst; /* long double */
  310.                    break;
  311.                default:
  312.                    errt2(yylval.t, "invalid float constant: ", yylval.t->image);
  313.                }
  314.             }
  315.          else {
  316.             /*
  317.              * This appears to be an integer constant. If it starts
  318.              *  with '0', it should be an octal constant.
  319.              */
  320.             if (yylval.t->image[0] == '0') {
  321.                s = yylval.t->image;
  322.                while (*s >= '0' && *s <= '7')
  323.                   ++s;
  324.                }
  325.             yylval.t->tok_id = int_suffix(s);
  326.             }
  327.          }
  328.       }
  329.    else if (yylval.t->tok_id == PpKeep) {
  330.       /*
  331.        * This is a non-standard preprocessor directive that must be
  332.        *  passed on to the output.
  333.        */
  334.       keepdir(yylval.t);
  335.       return yylex();
  336.       }
  337.    else if (lex_state == OpHead && yylval.t->tok_id != '}' &&
  338.      GoodChar(yylval.t->image[0])) {
  339.       /*
  340.        * This should be the operator symbol in the header of an operation
  341.        *  declaration. Concatenate all operator symbols into one token
  342.        *  of type OpSym.
  343.        */
  344.       sbuf = get_sbuf();
  345.       for (s = yylval.t->image; *s != '\0'; ++s)
  346.          AppChar(*sbuf, *s)
  347.       lk_ahead = preproc();
  348.       while (lk_ahead != NULL && GoodChar(lk_ahead->image[0])) {
  349.          for (s = lk_ahead->image; *s != '\0'; ++s)
  350.             AppChar(*sbuf, *s)
  351.          free_t(lk_ahead);
  352.          lk_ahead = preproc();
  353.          }
  354.       yylval.t->tok_id = OpSym;
  355.       yylval.t->image = str_install(sbuf);
  356.       rel_sbuf(sbuf);
  357.       }
  358.    else if (yylval.t->tok_id < 256) {
  359.       /*
  360.        * This is a one-character token, make sure it is valid.
  361.        */
  362.       if (!GoodChar(yylval.t->tok_id))
  363.          errt2(yylval.t, "invalid character: ", yylval.t->image);
  364.       }
  365.  
  366.    return yylval.t->tok_id;
  367.    }
  368.